package com.yulan.bankback.service.bank.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yulan.bankback.entity.event.LoginEvent;
import com.yulan.bankback.entity.model.bank.BankUser;
import com.yulan.bankback.entity.model.bank.UserMostLoginPlace;
import com.yulan.bankback.mapper.bank.BankUserMapper;
import com.yulan.bankback.mapper.bank.LoginEventMapper;
import com.yulan.bankback.mapper.bank.UserMostLoginPlaceMapper;
import com.yulan.bankback.service.bank.AuthService;
import com.yulan.bankback.service.bank.RedisService;
import com.yulan.bankback.service.ip.IpService;
import com.yulan.bankback.util.MD5Util;
import lombok.extern.slf4j.Slf4j;
import net.ipip.ipdb.IPFormatException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class AuthServiceImpl implements AuthService , InitializingBean {

    @Resource
    private BankUserMapper bankUserMapper;

    @Autowired
    private RedisService redisService;

    @Resource
    private LoginEventMapper loginEventMapper;

    @Autowired
    private IpService ipService;

    @Autowired
    private UserMostLoginPlaceMapper userMostLoginPlaceMapper;

    private static final long oneDay = 60 * 60 * 1000 * 24L;


    @Override
    public void afterPropertiesSet() throws Exception {
        List<UserMostLoginPlace> places = userMostLoginPlaceMapper.selectList(new QueryWrapper<>());
        places.forEach(item -> {
            redisService.hSet("most_login_place", item.getUid(),
                    item.getLoginPlaces(), oneDay, TimeUnit.MILLISECONDS);
        });
        log.info(">>>>>>>>>>>>>>> 已完成用户常登陆地预热 >>>>>>>>>>>>>>>");
    }


    private static final Long TOKEN_TTL = 60 * 60 * 24 * 1000L;

    @Override
    public String verifyPassword(String account, String password) {
        String encodePwd = MD5Util.encoderByMd5(password);
        BankUser bankUser = bankUserMapper.selectOne(
                new QueryWrapper<BankUser>().eq("account",account));
        if(bankUser != null && StringUtils.equals(bankUser.getPassword(), encodePwd))
            return bankUser.getId();

        return "";
    }

    @Override
    public String getToken(String account) {
        String token = UUID.randomUUID().toString().replaceAll("-","");
        redisService.set(token, "1", TOKEN_TTL, TimeUnit.MILLISECONDS);
        return token;
    }

    @Override
    public void removeToken(String token) {
        redisService.del(token);
    }

    @Override
    public boolean verifyToken(String token) {
        String targetToken = redisService.get(token);
        return StringUtils.isNotBlank(targetToken);
    }

    @Override
    public boolean verifyPayPassword(String uid, String payPassword) {
        BankUser bankUser = bankUserMapper.selectById(uid);
        if(bankUser == null) return false;
        String targetPassword = MD5Util.encoderByMd5(payPassword);
        return StringUtils.equals(targetPassword, bankUser.getPayPassword());
    }

    @Override
    public String register(String username, String account, String password,
                           String payPassword, String phone, String bornDate) {
        BankUser user = bankUserMapper.selectOne(
                new QueryWrapper<BankUser>().eq("phone", phone).or().eq("account",account));
        if(user != null)
            return "该用户已存在";
        String uid = UUID.randomUUID().toString().replaceAll("-","");
        BankUser newUser = new BankUser();
        newUser.setId(uid);
        newUser.setAccount(account);
        newUser.setMoney(0.0);
        newUser.setPassword(MD5Util.encoderByMd5(password));
        newUser.setPayPassword(MD5Util.encoderByMd5(password));
        newUser.setNotFreeMoney(0.0);
        newUser.setSafeScore(100);
        newUser.setUserName(username);
        newUser.setPhone(phone);
        newUser.setUserType(0);
        newUser.setBornDate(DateUtil.parseDate(bornDate));
        bankUserMapper.insert(newUser);
        return "success";
    }

    @Override
    public void insertLoginEvent(String uid, String ip, String type) {
        try {
            String city = ipService.findCityByIp(ip).getCityName();

            log.info("解析IP地址: {} 的结果: {}", ip, city);
            LoginEvent event = new LoginEvent();
            event.setLoginDate(new Date());
            event.setUid(uid);
            event.setLoginType(type);
            event.setLoginPlace(city);
            loginEventMapper.insert(event);
        } catch (IPFormatException | IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public String[] checkRemoteLogin(String uid, String ip) throws IPFormatException, IOException {
        String mostLoginCitys = redisService.hGetByKey("most_login_place", uid);
        if(StringUtils.isBlank(mostLoginCitys)){
            mostLoginCitys = userMostLoginPlaceMapper.selectOne(
                    new QueryWrapper<UserMostLoginPlace>()
                            .eq("uid",uid)).getLoginPlaces();
        }
        if(StringUtils.isBlank(mostLoginCitys)){
            //还没有该用户的数据，所以可以暂时认定为安全
            return new String[]{"safe"};
        }
        String city = ipService.findCityByIp(ip).getCityName();
        String[] citys = mostLoginCitys.split(",");
        Set<String> citySet = new HashSet<>(new ArrayList<>(Arrays.asList(citys)));
        if(StringUtils.isNotBlank(city) && !citySet.contains(city)){
            return new String[]{"unsafe", city};
        }
        return new String[]{"safe"};
    }


}
